/*******************************************************************************
* CSCI321 Major Project 2010 - University of Wollongong                        *
********************************************************************************
* Program:		WeaveEdit                                              *
* Authors:		Simon Allen (Student#: 3457527, Unix: sa655)           *
*			Scott Bellis (Student#: 3479110, Unix: sjb900)         *
*			Jason Benger (Student#: 3454137, Unix: jb960)          *
*			Timothy Newmarch (Student#: 3459263 Unix: tgn336)      *
*			Benjamin Richardson (Student# 3467752, Unix: bjr401)   *
* Supervisor:		Daniel F. Saffioti                                     *
* Modified:		28/10/2010                                             *
* Description:		WeaveEdit is a highly portable collaborative text      *
*			editor and word processor, allowing several users to   *
*			read and edit multiple documents at the same time.     *
*			It is available for Mac OS X, Windows and Linux,       *
*			utilising Nokia's Qt development framework.            *
*******************************************************************************/


#include "constants.h"
#include "welcomescreen.h"
#include "ui_welcomescreen.h"
#include "MainWindow/mainwindow.h"

#include <QAbstractTextDocumentLayout>
#include <QTextDocument>
#include <QDesktopServices>
#include <QUrl>


WelcomeScreen *WelcomeScreen::instance = NULL;

const int WelcomeScreen::MAX_RECENT_SESSIONS = 10;
const int WelcomeScreen::MAX_RECENT_TEXT_FILES = 5;
const int WelcomeScreen::MAX_RECENT_FORMATTED_FILES = 5;

/**
  * Manually paint and colour welcome screen items to custum behaviours.
  */
void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	QStyleOptionViewItemV4 optionV4 = option;
	initStyleOption(&optionV4, index);

	QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();

	QTextDocument doc;
	doc.setHtml(optionV4.text);

	/// Painting item without text
	optionV4.text = QString();
	style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);

	QAbstractTextDocumentLayout::PaintContext ctx;

	// Highlighting text if item is selected
	if (optionV4.state & QStyle::State_Selected)
		ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));

	QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
	painter->save();
	painter->translate(textRect.topLeft());
	painter->setClipRect(textRect.translated(-textRect.topLeft()));
	doc.documentLayout()->draw(painter, ctx);
	painter->restore();
}

/**
  * Return the correct sizehint of items.
  */
QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	QStyleOptionViewItemV4 optionV4 = option;
	QTextDocument doc;

	initStyleOption(&optionV4, index);

	doc.setHtml(optionV4.text);
	doc.setTextWidth(optionV4.rect.width());

	return QSize(doc.idealWidth(), doc.size().height());
}

WelcomeScreen::WelcomeScreen(QWidget *parent) : QWidget(parent), ui(new Ui::WelcomeScreen)
{
	ui->setupUi(this);

	settings = new QSettings(QString(PROGRAM_NAME).toLower(),
				 QString(PROGRAM_NAME).toLower(), this);

	// Create custom delegates so we can have HTML in list items.
	recentSessionsListDelegate = new HtmlDelegate();
	recentFilesListDelegate = new HtmlDelegate();
	helpListDelegate = new HtmlDelegate();

	// Set list delegates.
	ui->treeWidget_recentSessionsList->setItemDelegate(recentSessionsListDelegate);
	ui->treeWidget_recentFilesList->setItemDelegate(recentFilesListDelegate);
	ui->treeWidget_helpList->setItemDelegate(helpListDelegate);

	textFilesSection = new QTreeWidgetItem(ui->treeWidget_recentFilesList,
					       QStringList() << "<font color='black'><h3>Text Files</h3></font>");
	formattedFilesSection = new QTreeWidgetItem(ui->treeWidget_recentFilesList,
						    QStringList() << "<font color='black'><h3>Formatted Files</h3></font>");

	// Setup welcome help list.
	setupHelpList();

	textFilesSection->setExpanded(true);
	textFilesSection->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled);

	formattedFilesSection->setExpanded(true);
	formattedFilesSection->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled);

	connect(ui->treeWidget_recentSessionsList, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
		this, SLOT(dispatchRecentSession(QTreeWidgetItem*)));

	connect(ui->treeWidget_recentFilesList, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
		this, SLOT(dispatchRecentFile(QTreeWidgetItem*)));

	resize(MainWindow::getInstance()->size());

	loadRecentSessions();
	loadRecentFiles();
}

WelcomeScreen::~WelcomeScreen()
{
	delete ui;
	delete recentSessionsListDelegate;
	delete recentFilesListDelegate;
	delete helpListDelegate;

	ui = NULL;
	recentSessionsListDelegate = NULL;
	recentFilesListDelegate = NULL;
	helpListDelegate = NULL;
}


/**
  * Create the list of help items on the welcome screen.
  */
void WelcomeScreen::setupHelpList()
{
	helpHome = new QTreeWidgetItem(ui->treeWidget_helpList, QStringList()
			    << "<font color='black'><b>WeaveEdit Home</b><br><i>Visit WeaveEdit on the web</i></font>");

	helpUserManual = new QTreeWidgetItem(ui->treeWidget_helpList, QStringList()
			    << "<font color='black'><b>User Manual</b><br><i>Read the WeaveEdit user documentation</i></font>");

	helpTechManual = new QTreeWidgetItem(ui->treeWidget_helpList, QStringList()
			    << "<font color='black'><b>Technical Manual</b><br><i>For developers</i></font>");

	helpHome->setIcon(0, QIcon(":welcomeScreenIcons/images/welcomeScreen/list_bullet_arrow.png"));
	helpUserManual->setIcon(0, QIcon(":welcomeScreenIcons/images/welcomeScreen/list_bullet_arrow.png"));
	helpTechManual->setIcon(0, QIcon(":welcomeScreenIcons/images/welcomeScreen/list_bullet_arrow.png"));

	connect(ui->treeWidget_helpList, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
		this, SLOT(dispatchHelp(QTreeWidgetItem*)));
}

/**
  * Called when the user clicks a recent session to open, emits a signal to open the session file.
  */
void WelcomeScreen::dispatchRecentSession(QTreeWidgetItem *item)
{
	QString session = item->text(0);

	session = session.mid(session.indexOf("<i>") + 3);
	session = session.left(session.indexOf("</i>"));

	emit recentSessionSelected(session);
}

/**
  * Called when the user clicks a recent file to open, emits a signal to open the file.
  */
void WelcomeScreen::dispatchRecentFile(QTreeWidgetItem *item)
{
	QString file = item->text(0);

	file = file.mid(file.indexOf("<i>") + 3);
	file = file.left(file.indexOf("</i>"));

	emit recentFileSelected(file);
}

/**
  * Called when the user clicks a help item to open, opens the URL in the default browser. (hopefully not IE).
  */
void WelcomeScreen::dispatchHelp(QTreeWidgetItem *item)
{
	if (item == helpHome)
		QDesktopServices::openUrl(QUrl(WEBSITE_HOME));
}

/**
  * Adds a recent file to welcome screen, overriding the oldest one if there is too many.
  */
void WelcomeScreen::addRecentFile(const QString fileName, const Editor::Type type)
{
	qDebug("adding file: %s", fileName.toStdString().c_str());

	QTreeWidgetItem *newItem = NULL;
	QFileInfo fileInfo(fileName);
	QString desc = "<font color='black'><b>";
	QString iconFile = ":welcomeScreenIcons/images/welcomeScreen/list_bullet_arrow.png";

	desc += fileInfo.fileName() + "</b><br><i>" + fileInfo.canonicalFilePath() + "</i></font>";

	// If the file no longer exists, don't add it.
	if (!fileInfo.exists())
		return;

	qDebug("file exists!\n");

	if (type == Editor::TEXT)
	{
		for (int i = 0; i < textFilesSection->childCount(); i++)
		{
			if (textFilesSection->child(i)->text(0) == desc)
				return;
		}

		newItem = new QTreeWidgetItem(QStringList() << desc);

		newItem->setIcon(0, QIcon(iconFile));

		if (textFilesSection->childCount() >= MAX_RECENT_TEXT_FILES)
			textFilesSection->takeChild(MAX_RECENT_TEXT_FILES - 1);

		textFilesSection->insertChild(0, newItem);
	}

	else if (type == Editor::FORMATTED)
	{
		for (int i = 0; i < formattedFilesSection->childCount(); i++)
		{
			if (formattedFilesSection->child(i)->text(0) == desc)
				return;
		}

		newItem = new QTreeWidgetItem(QStringList() << desc);

		newItem->setIcon(0, QIcon(iconFile));

		if (formattedFilesSection->childCount() >= MAX_RECENT_FORMATTED_FILES)
			formattedFilesSection->takeChild(MAX_RECENT_FORMATTED_FILES - 1);

		formattedFilesSection->insertChild(0, newItem);
	}

	saveRecentFiles();
}

/**
  * Adds a new recent session to the list of recent sessions given it's name and it's location.
  */
void WelcomeScreen::addRecentSession(const QString sessionName, const QString fileName)
{
	QFileInfo fileInfo(fileName);
	QString desc = "<font color='black'><b>";
	QString iconFile = ":welcomeScreenIcons/images/welcomeScreen/list_bullet_arrow.png";

	desc += sessionName + "</b><br><i>" + fileInfo.canonicalFilePath() + "</i></font>";

	if (!fileInfo.exists())
		return;

	for (int i = 0; i < ui->treeWidget_recentSessionsList->topLevelItemCount(); i++)
	{
		if (ui->treeWidget_recentSessionsList->topLevelItem(i)->text(0) == desc)
			return;
	}

	QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList() << desc);

	newItem->setIcon(0, QIcon(iconFile));

	if (ui->treeWidget_recentSessionsList->topLevelItemCount() >= MAX_RECENT_SESSIONS)
		ui->treeWidget_recentSessionsList->takeTopLevelItem(MAX_RECENT_SESSIONS - 1);

	ui->treeWidget_recentSessionsList->insertTopLevelItem(0, newItem);

	saveRecentSessions();
}

/**
  * Loads recent sessions from the config file.
  */
void WelcomeScreen::loadRecentSessions()
{
	int i = 0;

	for (; i < MAX_RECENT_SESSIONS; i++)
	{
		QString settingName = "recentSession" + QString::number(i);
		QString sessionName = settings->value(settingName + "name").toString();
		QString sessionLoc = settings->value(settingName + "loc").toString();

		if (sessionName.isEmpty() || sessionLoc.isEmpty())
			break;

		addRecentSession(sessionName, sessionLoc);
	}

	// Check if there are any recent sessions, if not put up a message.
	if (i == 0)
	{

	}

	// If some files were not found, these should removed from the config file.
	saveRecentSessions();
}

/**
  * Loads recent files from the config file.
  */
void WelcomeScreen::loadRecentFiles()
{
	qDebug("loading files from file");
	int i = 0;

	// Loop for each text file.
	for (; i < MAX_RECENT_TEXT_FILES; i++)
	{
		QString settingName = "recentTextFile" + QString::number(i);
		QString fileName = settings->value(settingName).toString();

		qDebug("trying to load: %s", fileName.toStdString().c_str());
		if (fileName.isEmpty())
			break;

		qDebug("file exists!");

		addRecentFile(fileName, Editor::TEXT);
	}

	// Check if there are any recent text files, if not put up a message.
	if (i == 0)
	{

	}

	i = 0;

	// Loop for each formatted file.
	for (; i < MAX_RECENT_FORMATTED_FILES; i++)
	{
		QString settingName = "recentFormattedFile" + QString::number(i);
		QString fileName = settings->value(settingName).toString();

		if (fileName.isEmpty())
			break;

		addRecentFile(fileName, Editor::FORMATTED);
	}

	// Check if there are any recent formatted files, if not put up a message.
	if (i == 0)
	{

	}

	saveRecentFiles();
}

/**
  * Save recent sessions to config file.
  */
void WelcomeScreen::saveRecentSessions()
{
	for (int i = 0; i < MAX_RECENT_SESSIONS; i++)
	{
		QString settingName = "recentSession" + QString::number(i);

		QTreeWidgetItem *session = ui->treeWidget_recentSessionsList->topLevelItem(i);

		if (!session)
			settings->remove(settingName);

		else
		{
			QString sessionText = session->text(0);
			int sessionNameStart = sessionText.indexOf("<b>") + 3;
			int sessionLocStart = sessionText.indexOf("<i>") + 3;

			QString sessionName = sessionText.mid(sessionNameStart,
							      sessionText.indexOf("</b>") - sessionNameStart);

			QString sessionLoc = sessionText.mid(sessionLocStart,
							     sessionText.indexOf("</i>") - sessionLocStart);

			settings->setValue(settingName + "name", sessionName);
			settings->setValue(settingName + "loc", sessionLoc);
		}
	}
}

/**
  * Save recent files to config file.
  */
void WelcomeScreen::saveRecentFiles()
{
	qDebug("saving files to settings file");

	// Loop for each text file.
	for (int i = 0; i < MAX_RECENT_TEXT_FILES; i++)
	{
		QString settingName = "recentTextFile" + QString::number(i);

		QTreeWidgetItem *file = textFilesSection->child(i);

		if (!file)
		{
			qDebug("file doens't exist %i", i);
			settings->remove(settingName);
		}
		else
		{
			QString fileText = file->text(0);
			int fileNameStart = fileText.indexOf("<i>") + 3;

			QString fileName = fileText.mid(fileNameStart,
							      fileText.indexOf("</i>") - fileNameStart);

			qDebug("putting into file: %s", fileName.toStdString().c_str());

			settings->setValue(settingName, fileName);
		}
	}

	// Loop for each formatted file.
	for (int i = 0; i < MAX_RECENT_FORMATTED_FILES; i++)
	{
		QString settingName = "recentFormattedFile" + QString::number(i);

		QTreeWidgetItem *file = formattedFilesSection->child(i);

		if (!file)
			break;

		QString fileText = file->text(0);
		int fileNameStart = fileText.indexOf("<i>") + 3;

		QString fileName = fileText.mid(fileNameStart,
						      fileText.indexOf("</i>") - fileNameStart);

		settings->setValue(settingName, fileName);
	}
}
